package cn.xiaosiyuan.util.XMLFile.interfaces;

import cn.xiaosiyuan.util.X;
import cn.xiaosiyuan.util.XMLFile.XmlUtil;
import cn.xiaosiyuan.util.XMLFile.annotation.GetValueFromXML;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public interface FillXmlFields {

    default void initXmlFields(Class<?> cl) {
        
    }


    default void initXmlValues(Class<?> cl) throws IllegalAccessException {
        Field[] fields = cl.getDeclaredFields();
        for (Field field : fields) {
            GetValueFromXML annotation = field.getDeclaredAnnotation(GetValueFromXML.class);
            if (annotation != null) {
                field.setAccessible(true);
                String methodName = annotation.realPathMethod();
                Method[] declaredMethods = cl.getDeclaredMethods();

                try {
                    Method method = cl.getMethod(methodName, null);
                    if (method != null) {
                        try {
                            /*
                            报错
                            String realPath = (String) method.invoke(this, (Object) null);
                             */
                            String realPath = (String) method.invoke(this, null);
                            field.set(this, getXMLValue(realPath, annotation.tagName()));
                        } catch (InvocationTargetException e) {
                            field.set(this, annotation.defaultValue());
                        }
                    } else {
                        field.set(this, annotation.defaultValue());
                    }
                } catch (NoSuchMethodException e) {
                    field.set(this, annotation.defaultValue());
                }

            }
        }
    }

    default Method getRealPathMethod(String methodName, Method[] declaredMethods) {
        Method method = null;
        for (Method m : declaredMethods) {
            String methodNameClass = m.getName();
            Class<?> returnType = m.getReturnType();
            Class<?>[] parameterTypes = m.getParameterTypes();
            if (methodNameClass.equals(methodName)
                    && returnType.isAssignableFrom(String.class)
                    && parameterTypes.length == 0
            ) {
                method = m;
                break;
            }
        }
        return method;
    }


    /*
    <property key="create_time" value="制单日期"/>

    return "制单日期";
     */
    default String getXMLValue(String realPath, String tagName) {
        String value = "";
        List<Map<String, String>> list = X.xmlUtil.parseXMLToList(realPath);
        for (Map<String, String> map : list) {
            if (map.containsKey("key") && map.get("key").equalsIgnoreCase(tagName)) {
                value = map.getOrDefault("value", "");
                break;
            }
        }
        return value;
    }


    /*
    例子：
    <map name="header">
        <property key="create_time" value="制单日期"/>
        <property key="project_name" value="项目名称"/>
        <property key="bill_code" value="合同编号"/>
    </map>

    return map;
    map.toString {create_time=制单日期, bill_code=合同编号, project_name=项目名称}

     */
    default Map<String, String> getMap(String realPath,String mapName) {
        Map<String, String> map = new HashMap<>();

        String parentId = "";
        List<Map<String, String>> list = X.xmlUtil.parseXMLToList(realPath);


        for (Map<String, String> m : list) {
            if (m.get("TagName").equalsIgnoreCase("map") && m.get("name").equalsIgnoreCase(mapName)) {
                parentId = m.getOrDefault("id", "");
            }
            String curParentId = m.getOrDefault("parent_id", "");
            if(!parentId.equals("") && parentId.equals(curParentId)) {
                map.put(m.getOrDefault("key", ""), m.getOrDefault("value", ""));
            }
            // 后面的就不需要再循环了
            if(!parentId.equals("") && !parentId.equals(curParentId)) {
                break;
            }
        }

        return map;
    }

}
